/*
 * Copyright (C) 2011 Young,Fey <fey.young@gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.youngfey.util
import groovy.util.logging.*
import groovy.transform.*

/**
 * 资源操作。包括文件操作和从代码树下获取资源
 * @author Young,Fey <fey.young@gmail.com>
 */
@Log
class ResourceUtil {
    private static URL getResource(String name, Class c = ResourceUtil.class) {
        c.classLoader.getResource(name)
    }

    /**
     * 在代码树中查找指定的资源并返回InputStream
     */
    static InputStream getResourceAsStream(String name, Class c = ResourceUtil.class) {
        c.classLoader.getResourceAsStream(name)
    }

    /**
     * 查找指定资源并返回文本内容
     */
    static String getText(String name, Class c = ResourceUtil.class) {
        getResource(name, c)?.text
    }

    /**
     * 查找指定资源并返回文本内容
     */
    static String getText(String name, String charset,
             Class c = ResourceUtil.class) {
        getResource(name, c)?.getText(charset)
    }

    private static verifyFile = { 
        assert it != null
        assert !it.isDirectory()
    }

    private static verifyDir = { 
        assert it != null
        assert !it.isFile()
        it.mkdirs()
    }

    /**
     * 将代码树中资源写入到指定文件
     * @param name 待查找的资源名称
     * @param destination 待写入的文件
     * @param overwrite 是否覆盖原有文件
     * @return 写入是否成功
     */
    static boolean extract(String name, File destination, boolean overwrite = true, 
            Class c = ResourceUtil.class) {
        verifyFile destination
        if(overwrite) destination.delete()
        else {
            if(destination.size() > 0) return false
        }
        destination.createNewFile()
        log.info 'Extract: destination ok'
        def is = getResourceAsStream(name, c)
        if(!is) return false
        log.info 'Extract: input stream ok'
        destination << is
        log.info 'Extract: done'
        true
    }

    /**
     * 将资源中某个目录下的所有文件都写入到指定文件夹
     */
    static boolean extractDir(String name, File directory, boolean overwrite = true,
            Class c = ResourceUtil.class) {
        verifyDir directory
        def url = getResource(name, c)
        if(url == null) return false
        def dir
        try {
            dir = new File(url.toURI())
        } catch(IllegalArgumentException e) {
            println "URI is not hierarchical, please rebuild metakit.jar on the same Operating System which you run this program"
            throw e
        }
        copyDir(dir, directory, overwrite)
    }

    /**
     * 复制文件
     */
    static boolean copy(File src, File dir, boolean overwrite = false) {
        verifyDir dir
        if(!src.isFile()) {
            log.warning "Copy: src $src is directory or not existed"
            return false
        }
        def file = new File(dir, src.name)
        if(file.exists()) {
            log.warning "Copy: file $file exists"
            return false
        }

        file.createNewFile()
        file << src.newInputStream()
        log.info "Copy Done: $file"
        true
    }

    /**
     * 将指定文件夹下的内容复制到目标文件夹
     */
    static boolean copyDir(File src, File dir, boolean overwrite = false) {
        verifyDir dir
        verifyDir src
        if(!src.exists()) {
            log.warning "Copy: src $src is not existed"
            return false
        }

        boolean flag = true
        src.eachFile { file ->
            if(!copy(file, dir, overwrite)) flag = false
        }
        log.info "CopyDir returns $flag: $src"
        flag
    }
}

